#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "syntax.h"
#include "symbol.h"
#include "tools.h"

void initFunction(FILE *fp_out, char *name, char *type);
int analyseCompUnit(FILE *fp_in, FILE *fp_out);
void analyseGlobalConstDef(FILE *fp_in, FILE *fp_out);
Inter_var *analyseGlobalConstInitVal(FILE *fp_in, FILE *fp_out, Ident *ident, int depth);
Inter_var *analyseLocalConstInitVal(FILE *fp_in, FILE *fp_out, Ident *ident, int depth, int *loc);
Inter_var *analyseInitVal(FILE *fp_in, FILE *fp_out, Ident *ident, int depth, int *loc);
void analyseGlobalVarDef_(FILE *fp_in, FILE *fp_out, char *i, char *type);
void analyseGlobalVarDef(FILE *fp_in, FILE *fp_out);
void analyseFuncDef(FILE *fp_in, FILE *fp_out, char *i, char *type);
void analyseFuncFParam(FILE *fp_in, FILE *fp_out,Ident *ident, int cnt_param);
void analyseBlock(FILE *fp_in, FILE *fp_out, int mode);     // 0:不带{}; 1:带{}
void analyseFuncBlock(FILE *fp_in, FILE *fp_out, Ident *function);
void analyseBlockItem(FILE *fp_in, FILE *fp_out);
void analyseDecl(FILE *fp_in, FILE *fp_out);
void analyseConstDef(FILE *fp_in, FILE *fp_out);
void analyseVarDef(FILE *fp_in, FILE *fp_out);
void analyseStmt(FILE *fp_in, FILE *fp_out);
int analyseWhileStmt(FILE *fp_in, FILE *fp_out, int to_continue, int to_break);
void analyseWhileBlock(FILE *fp_in, FILE *fp_out, int to_continue, int to_break);
int analyseWhileBlockItem(FILE *fp_in, FILE *fp_out, int to_continue, int to_break);
Inter_var *analyseCond(FILE *fp_in, FILE *fp_out);
Inter_var *analyseLOrExp(FILE *fp_in, FILE *fp_out);
Inter_var *analyseLAndExp(FILE *fp_in, FILE *fp_out);
Inter_var *analyseEqExp(FILE *fp_in, FILE *fp_out);
Inter_var *analyseRelExp(FILE *fp_in, FILE *fp_out);
Inter_var *analyseExp(FILE *fp_in, FILE *fp_out, int mode);
Inter_var *analyseFuction(FILE *fp_in, FILE *fp_out, char name[]);
void specify(FILE *fp_out, int mode, Inter_var vars[], int *top_var, enum operator opt);
void printLLVM(FILE *fp_out, Inter_var vars[], int *top_var, char *str, Inter_var a, Inter_var b);
void printCondLLVM(FILE *fp_out, char *str, Inter_var *a, Inter_var *b);
void printArrayScaleLLVM(FILE *fp_out, Ident *ident, int dim);
int getArrayByte(Ident *ident);
int getBlankLoc(Ident *ident, int depth);

void syntaxAnalysis(char *file_input, char *file_output) {
    // 打开文件
    FILE *fp_in, *fp_out;
    if ((fp_in = fopen(file_input, "r")) == NULL) {
        printf("File open error!\n");
        exit(-1);
    }
    if ((fp_out = fopen(file_output, "w")) == NULL) {
        printf("File open error!\n");
        exit(-1);
    }

    // 数据结构初始化
    memset(hold, '\0', sizeof(hold));
    table_global->zone[++(table_global->top_zone)] = 0;     // 栈底为全局变量的开始
    initFunction(fp_out, "getint", "Int");
    initFunction(fp_out, "getch", "Int");
    initFunction(fp_out, "putint", "Void");
    initFunction(fp_out, "putch", "Void");
    initFunction(fp_out, "putarray", "Void");
    initFunction(fp_out, "getarray", "Int");
    initFunction(fp_out, "memset", "Void");
    fprintf(fp_out, "\n");

    // 逐行读入语法分析
    fscanf(fp_in, "%s", hold);
    while(strlen(hold) != 0) {
        int flag_decl = 1;
        int old_flag = 0;

        // CompUnit语法判断
        while (isCompUnitBegin(hold)) {
            old_flag = flag_decl;
            flag_decl = analyseCompUnit(fp_in, fp_out);
        }

        if (strlen(hold) != 0 ) {
            printf("Wrong start!\n");
            exit(2);    // 语法错误
        }
    }

    // 关闭文件
    fclose(fp_in);
    fclose(fp_out);
}

void initFunction(FILE *fp_out, char *name, char *type) {
    Ident *ident = (Ident *)malloc(sizeof(Ident));
    strcpy(ident->name, name);
    strcpy(ident->type, type);
    ident->address = -1;
    ident->def = 2;     // 函数

    if (strcmp(name, "memset") == 0) { 
        fprintf(fp_out, "declare void @memset(i32*, i32, i32)\n");
        ident->param_num = 3;
    }
    else if (strcmp(name, "getch") == 0 || strcmp(name, "getint") == 0) { 
        fprintf(fp_out, "declare i32 @%s()\n", name); 
        ident->param_num = 0;
        strcpy(ident->type, "Int");
    }
    else if (strcmp(name, "putch") == 0 || strcmp(name, "putint") == 0) {
        fprintf(fp_out, "declare void @%s(i32)\n", name); 
        ident->param_num = 1;
        strcpy(ident->type, "Void");
        Ident *param = (Ident *)malloc(sizeof(Ident));
        param->dimension = 0;
        ident->params[0] = param;
    }
    else if (strcmp(name, "getarray") == 0) {
        fprintf(fp_out, "declare i32 @%s(i32*)\n", name); 
        ident->param_num = 1;
        strcpy(ident->type, "Int");
        Ident *param = (Ident *)malloc(sizeof(Ident));
        param->dimension = 1;
        ident->params[0] = param;
    }
    else if (strcmp(name, "putarray") == 0) {
        fprintf(fp_out, "declare void @%s(i32, i32*)\n", name);
        ident->param_num = 2;
        strcpy(ident->type, "Void");
        Ident *param1 = (Ident *)malloc(sizeof(Ident));
        Ident *param2 = (Ident *)malloc(sizeof(Ident));
        param1->dimension = 0;
        ident->params[0] = param1;
        param2->dimension = 1;
        ident->params[1] = param2;
    }
    insertItem(ident, table_global);
}

bool isCompUnitBegin(char str[]) {
    return isDeclBegin(str) || isFuncDefBegin(str);
}

bool isFuncDefBegin(char str[]) {
    return (strcmp(str, "Int") == 0) || (strcmp(str, "Void") == 0);
}

bool isBlockItemBegin(char str[]) {
    return isDeclBegin(str) || isStmtBegin(str);
}

bool isDeclBegin(char str[]) {
    return (strcmp(str, "Const") == 0) || (strcmp(str, "Int") == 0);
}

bool isStmtBegin(char str[]) {
    return (strcmp(str, "Return") == 0) 
    || isIdentBegin(str) || isExpBegin(str) 
    || (strcmp(str, "Semicolon") == 0)
    || (strcmp(str, "If") == 0)
    || (strcmp(str, "LBrace") == 0)
    || (strcmp(str, "While") == 0)
    || (strcmp(str, "Break") == 0)
    || (strcmp(str, "Continue") == 0);
}

bool isIdentBegin(char str[]) {
    return (strncmp(str, "Ident", 5) == 0);
}

bool isFuncBegin(char str[]) {
    if (strncmp(str, "Ident", 5) == 0) {
        char temp[MAXLEN];
        strcpy(temp, str);
        slice(temp, 6, strlen(temp)-2);
        Ident *ident = findGlobalItem(temp, table_global);
        if (ident != NULL && ident->def == 2)
            return 1;
    } 
    return 0;
}

bool isExpBegin(char str[]) {
    return isNumber(str) || isIdentBegin(str) || (strcmp(hold, "LPar") == 0) || (strcmp(hold, "Minus") == 0) || (strcmp(hold, "Plus") == 0);
}

bool isExpCompositon(char str[]) {
    return isNumber(str) 
    || isIdentBegin(str) 
    || (strcmp(hold, "LPar") == 0)
    || (strcmp(hold, "RPar") == 0)
    || (strcmp(hold, "Mult") == 0)
    || (strcmp(hold, "Div") == 0)
    || (strcmp(hold, "Rem") == 0)
    || (strcmp(hold, "Minus") == 0) 
    || (strcmp(hold, "Plus") == 0)
    || (strcmp(hold, "Rev") == 0);
}

bool isArray(char str[]) {
    char t[MAXLEN];
    memset(t, '\0', sizeof(t));
    strcpy(t, str);
    slice(t, 6, strlen(t)-2);
    Ident *ident = findGlobalItem(t, table_global);
    return ident != NULL && ident->dimension > 0;
}

int analyseCompUnit(FILE *fp_in, FILE *fp_out) {
    // ConstDecl
    if (strcmp(hold, "Const") == 0) {
        memset(hold, '\0', sizeof(hold));
        fscanf(fp_in, "%s", hold);

        // Btype
        if (strcmp(hold, "Int") != 0) {
            exit(2);   // 语法错误
        }
        memset(hold, '\0', sizeof(hold));
        fscanf(fp_in, "%s", hold);

        // ConstDef
        if (isIdentBegin(hold)) {
            analyseGlobalConstDef(fp_in, fp_out);
        } else {
            exit(2);   // 语法错误
        }

        while (strcmp(hold, "Comma") == 0) {
            memset(hold, '\0', sizeof(hold));
            fscanf(fp_in, "%s", hold);
            if (isIdentBegin(hold)) {
                analyseGlobalConstDef(fp_in, fp_out);
            } else {
                exit(2);   // 语法错误
            }
        }

        // ';'
        if (strcmp(hold, "Semicolon") != 0) {
            exit(2);   // 语法错误
        }
        memset(hold, '\0', sizeof(hold));
        fscanf(fp_in, "%s", hold);

        return 1;
    }
    // VarDecl & FuncDef
    else {
        char ident[MAXLEN];
        char type[MAXLEN];
        memset(ident, '\0', sizeof(ident));
        memset(ident, '\0', sizeof(type));
        strcpy(type, hold);
        memset(hold, '\0', sizeof(hold));
        fscanf(fp_in, "%s", hold);

        // Ident
        if (!isIdentBegin(hold)) {
            printf("CompUnit error!\n");
            exit(2);    // 语法错误
        } else {
            strcpy(ident, hold);
        }
        memset(hold, '\0', sizeof(hold));
        fscanf(fp_in, "%s", hold);

        if (strcmp(hold, "LPar") == 0) {
            // FuncDef
            analyseFuncDef(fp_in, fp_out, ident, type);
            return 0;
        } else {
            // VarDecl
            analyseGlobalVarDef_(fp_in, fp_out, ident, type);

            // ','
            while (strcmp(hold, "Comma") == 0) {
                memset(hold, '\0', sizeof(hold));
                fscanf(fp_in, "%s", hold);
                if (isIdentBegin(hold)) {
                    analyseGlobalVarDef(fp_in, fp_out);
                } else {
                    exit(2);   // 语法错误
                }
            }

            // ';'
            if (strcmp(hold, "Semicolon") != 0) {
                exit(2);   // 语法错误
            }
            memset(hold, '\0', sizeof(hold));
            fscanf(fp_in, "%s", hold);

            return 1;
        }
    }
}

/* type & ident & '(' already read and checked */
void analyseFuncDef(FILE *fp_in, FILE *fp_out, char *i, char *type) {
    if (strcmp(type, "Void") == 0) {
        fprintf(fp_out, "\ndefine dso_local void ");
    } else {
        fprintf(fp_out, "\ndefine dso_local i32 ");
    }

    // Ident
    slice(i, 6, strlen(i)-2);
    fprintf(fp_out, "@%s", i);
    // 符号表操作
    if (isInTable(i, table_global)) {        
        printf("Global ident exist!\n");
        exit(3);    // 语义错误
    }
    Ident *ident = (Ident *)malloc(sizeof(Ident));
    strcpy(ident->name, i);
    strcpy(ident->type, type);
    ident->address = -1;
    ident->value = 0;
    ident->def = 2;     // 函数
    ident->dimension = 0;
    ident->param_num = 0;
    insertItem(ident, table_global);

    // '('
    fprintf(fp_out, "(");
    memset(hold, '\0', sizeof(hold));
    fscanf(fp_in, "%s", hold);

    // 符号表作用域更新
    table_global->zone[++(table_global->top_zone)] = table_global->top_list + 1;

    // FuncFParams
    if (strcmp(hold, "RPar") != 0) {
        int cnt_param = 1;
        // FuncFParam
        analyseFuncFParam(fp_in, fp_out, ident, cnt_param);

        while (strcmp(hold, "Comma") == 0) {
            fprintf(fp_out, ", ");
            cnt_param++;
            memset(hold, '\0', sizeof(hold));
            fscanf(fp_in, "%s", hold);
            // FuncFParam
            analyseFuncFParam(fp_in, fp_out, ident, cnt_param);
        }
        ident->param_num = cnt_param;
    }

    // ')'
    if (strcmp(hold, "RPar") == 0 ) {
        fprintf(fp_out, ")");
    } else {
        exit(2);   // 语法错误
    }
    memset(hold, '\0', sizeof(hold));
    fscanf(fp_in, "%s", hold);
    
    // FuncBlock
    analyseFuncBlock(fp_in, fp_out, ident);

    // 符号表作用域更新
    table_global->top_list = table_global->zone[(table_global->top_zone)] - 1;
    table_global->top_zone--;
}

void analyseFuncFParam(FILE *fp_in, FILE *fp_out, Ident *ident, int cnt_param) {
    // Btype
    if (strcmp(hold, "Int") != 0) {
        printf("Param type wrong!\n");
        exit(2);    // 语法错误
    }
    memset(hold, '\0', sizeof(hold));
    fscanf(fp_in, "%s", hold);

    // Ident
    if (isIdentBegin(hold)) {
        slice(hold, 6, strlen(hold)-2);
        // 符号表操作
        if (isInTable(hold, table_global)) {        
            printf("Param exists!\n");
            exit(3);    // 语义错误
        }
        Ident *param = (Ident *)malloc(sizeof(Ident));
        strcpy(param->name, hold);
        strcpy(param->type, "int");
        param->value = 1;
        param->def = 5;     // 参数
        param->dimension = 0;
        param->address = -1;
        insertItem(param, table_global);
        ident->params[cnt_param-1] = param;

        memset(hold, '\0', sizeof(hold));
        fscanf(fp_in, "%s", hold);

        // 数组作为参数
        while (strcmp(hold, "LBracket") == 0) {
            memset(hold, '\0', sizeof(hold));
            fscanf(fp_in, "%s", hold);
            if (param->dimension == 0) {
                if (strcmp(hold, "RBracket") != 0) {
                    printf("Do not need dimension!\n");
                    exit(3);    // 语义错误
                }
                else {
                    memset(hold, '\0', sizeof(hold));
                    fscanf(fp_in, "%s", hold);
                    param->dimension++;
                    continue;
                }
            }

            Inter_var *index = analyseExp(fp_in, fp_out, 1);

            // index > 0 语义检查
            if (index->value <= 0) {
                printf("Wrong array length!\n");
                exit(1);    // 语义错误
            } else {
                param->index[param->dimension++] = index->value;
            }

            if (strcmp(hold, "RBracket") != 0) {
                printf("']' missed!/n");
                exit(1);    // 语法错误
            }
            memset(hold, '\0', sizeof(hold));
            fscanf(fp_in, "%s", hold);
        }

    // LLVM
    param->address = ++register_cnt;
    if (param->dimension == 0) {
        fprintf(fp_out, "i32 %%x%d", param->address);
    } else if (param->dimension == 1) {
        fprintf(fp_out, "i32* %%x%d", param->address);
    } else {
        printArrayScaleLLVM(fp_out, param, 1);
        fprintf(fp_out, "* %%x%d", param->address);
    }
    

    } else {
        printf("Param name wrong!\n");
        exit(2);    // 语法错误
    }

}

void analyseGlobalConstDef(FILE *fp_in, FILE *fp_out) {
    // Ident
    slice(hold, 6, strlen(hold)-2);
    if (isInTable(hold, table_global)) {        // 符号表操作
        printf("Ident exist!\n");
        exit(3);    // 语义错误
    }

    Ident *ident = (Ident *)malloc(sizeof(Ident));
    strcpy(ident->name, hold);
    strcpy(ident->type, "int");
    ident->address = -1;
    ident->value = 0;
    ident->def = 1;
    ident->dimension = 0;

    memset(hold, '\0', sizeof(hold));
    fscanf(fp_in, "%s", hold);

    // '[' 数组
    while (strcmp(hold, "LBracket") == 0) {
        ident->def = 4;
        memset(hold, '\0', sizeof(hold));
        fscanf(fp_in, "%s", hold);
        Inter_var *index = analyseExp(fp_in, fp_out, 1);

        // index>0 语义检查
        if (index->value <= 0) {
            printf("Wrong array length!\n");
            exit(1);    // 语义错误
        } else {
            ident->index[ident->dimension++] = index->value;
        }

        if (strcmp(hold, "RBracket") != 0) {
            printf("']' missed!/n");
            exit(1);    // 语法错误
        }
        memset(hold, '\0', sizeof(hold));
        fscanf(fp_in, "%s", hold);
    }

    // 入符号表
    insertItem(ident, table_global);

    // 全局常量数组打印信息
    if (ident->dimension > 0) {
        fprintf(fp_out, "@%s = dso_local constant ", ident->name);
    }

    // '='
    if (strcmp(hold, "Assign") != 0) {
        printf("Const def error!\n");
        exit(2);    // 语法错误
    }
    memset(hold, '\0', sizeof(hold));
    fscanf(fp_in, "%s", hold);

    // ConstInitial
    Inter_var *result = analyseGlobalConstInitVal(fp_in, fp_out, ident, 0);
    if (result != NULL) {
        ident->value = result->value;
    } else {
        fprintf(fp_out, "\n");
    }
}

Inter_var *analyseGlobalConstInitVal(FILE *fp_in, FILE *fp_out, Ident *ident, int depth) {
    // '{'
    if (strcmp(hold, "LBrace") == 0) {
        memset(hold, '\0', sizeof(hold));
        fscanf(fp_in, "%s", hold);

        printArrayScaleLLVM(fp_out, ident, depth);

        if (strcmp(hold, "RBrace") != 0) {
            
            fprintf(fp_out, "["); //

            Inter_var *result = analyseGlobalConstInitVal(fp_in, fp_out, ident, depth+1);

            if (result != NULL) { fprintf(fp_out, "i32 %d", result->value); } //

            int cnt = 1;
            while (strcmp(hold, "Comma") == 0 || cnt < ident->index[depth]) {
                fprintf(fp_out, ", "); //
                if (strcmp(hold, "Comma") == 0) {
                    memset(hold, '\0', sizeof(hold));
                    fscanf(fp_in, "%s", hold);
                    Inter_var *result = analyseGlobalConstInitVal(fp_in, fp_out, ident, depth+1);
                    
                    if (result != NULL) { fprintf(fp_out, "i32 %d", result->value); } //
                }
                // 补充零
                else {
                    if (depth+1 == ident->dimension) { fprintf(fp_out, "i32 0"); }
                    else {
                        printArrayScaleLLVM(fp_out, ident, depth+1);
                        fprintf(fp_out, "zeroinitializer"); //
                    }
                }
                cnt++;
            }

            fprintf(fp_out, "]"); //

        } else {
            // 空括号情况
            fprintf(fp_out, "zeroinitializer"); //
        }

        if (strcmp(hold, "RBrace") != 0 ) {
            printf("Array decl no RBrace!\n");
            exit(2);    // 语法错误
        }

        memset(hold, '\0', sizeof(hold));
        fscanf(fp_in, "%s", hold);
        return NULL;
    }
    else {
        // Exp
        return analyseExp(fp_in, fp_out, 1);
    }
}

/* type & name & syn already read and checked */
void analyseGlobalVarDef_(FILE *fp_in, FILE *fp_out, char *i, char *type) {
    // Int
    if (strcmp(type, "Int") != 0) {
        printf("Var must be int!\n");
        exit(2);    // 语法错误
    }

    // Ident
    slice(i, 6, strlen(i)-2);
    // 符号表操作
    if (isInTable(i, table_global)) {        
        printf("Global ident exist!\n");
        exit(3);    // 语义错误
    }

    // 新建符号表元素
    Ident *ident = (Ident *)malloc(sizeof(Ident));
    strcpy(ident->name, i);
    strcpy(ident->type, "int");
    ident->address = -1;
    ident->value = 0;
    ident->def = 3;     // 全局变量
    ident->dimension = 0;

    // '[' 数组
    while (strcmp(hold, "LBracket") == 0) {
        memset(hold, '\0', sizeof(hold));
        fscanf(fp_in, "%s", hold);
        Inter_var *index = analyseExp(fp_in, fp_out, 1);

        // index>0 语义检查
        if (index->value <= 0) {
            printf("Wrong array length!\n");
            exit(1);    // 语义错误
        } else {
            ident->index[ident->dimension++] = index->value;
        }

        if (strcmp(hold, "RBracket") != 0) {
            printf("']' missed!/n");
            exit(1);    // 语法错误
        }
        memset(hold, '\0', sizeof(hold));
        fscanf(fp_in, "%s", hold);
    }

    insertItem(ident, table_global);

    // 全局数组打印信息
    if (ident->dimension > 0) {
        fprintf(fp_out, "@%s = dso_local global ", ident->name);
        // // 递归
        // printArrayScaleLLVM(fp_out, ident, 0);
    }

    // '='
    if (strcmp(hold, "Assign") == 0) {
        memset(hold, '\0', sizeof(hold));
        fscanf(fp_in, "%s", hold);

        // ConstInitial
        Inter_var *result = analyseGlobalConstInitVal(fp_in, fp_out, ident, 0);
        if (result != NULL) {
            ident->value = result->value;
            fprintf(fp_out, "@%s = dso_local global i32 %d\n", ident->name, ident->value);
        } else {
            fprintf(fp_out, "\n");
        }
    } else {
        if (ident->dimension == 0) {
            fprintf(fp_out, "@%s = dso_local global i32 0\n", ident->name);
        }
        else {
            // printf("===dim: %d===\n===%d * %d===\n", ident->dimension, ident->index[0], ident->index[1]);
            printArrayScaleLLVM(fp_out, ident, 0);
            fprintf(fp_out, "zeroinitializer\n");
        }
    }
}

void analyseGlobalVarDef(FILE *fp_in, FILE *fp_out) {
    // Ident
    slice(hold, 6, strlen(hold)-2);
    // 符号表操作
    if (isInTable(hold, table_global)) {        
        printf("Global ident exist!\n");
        exit(3);    // 语义错误
    }

    Ident *ident = (Ident *)malloc(sizeof(Ident));
    strcpy(ident->name, hold);
    strcpy(ident->type, "int");
    ident->address = -1;
    ident->value = 0;
    ident->def = 3;     // 全局变量
    ident->dimension = 0;

    memset(hold, '\0', sizeof(hold));
    fscanf(fp_in, "%s", hold);

    // '[' 数组
    while (strcmp(hold, "LBracket") == 0) {
        memset(hold, '\0', sizeof(hold));
        fscanf(fp_in, "%s", hold);
        Inter_var *index = analyseExp(fp_in, fp_out, 1);

        // index>0 语义检查
        if (index->value <= 0) {
            printf("Wrong array length!\n");
            exit(1);    // 语义错误
        } else {
            ident->index[ident->dimension++] = index->value;
        }

        if (strcmp(hold, "RBracket") != 0) {
            printf("']' missed!/n");
            exit(1);    // 语法错误
        }
        memset(hold, '\0', sizeof(hold));
        fscanf(fp_in, "%s", hold);
    }

    insertItem(ident, table_global);

    // 全局数组打印信息
    if (ident->dimension > 0) {
        fprintf(fp_out, "@%s = dso_local global ", ident->name);
    }

    // '='
    if (strcmp(hold, "Assign") == 0) {
        memset(hold, '\0', sizeof(hold));
        fscanf(fp_in, "%s", hold);

        // ConstInitial
        Inter_var *result = analyseGlobalConstInitVal(fp_in, fp_out, ident, 0);
        if (result != NULL) {
            ident->value = result->value;
            fprintf(fp_out, "@%s = dso_local global i32 %d\n", ident->name, ident->value);
        } else {
            fprintf(fp_out, "\n");
        }
    } else {
        if (ident->dimension == 0) {
            fprintf(fp_out, "@%s = dso_local global i32 0\n", ident->name);
        }
        else {
            // printf("===dim: %d===\n===%d * %d===\n", ident->dimension, ident->index[0], ident->index[1]);
            printArrayScaleLLVM(fp_out, ident, 0);
            fprintf(fp_out, "zeroinitializer\n");
        }
    }
}

void analyseBlock(FILE *fp_in, FILE *fp_out, int mode) {
    // 符号表作用域更新
    table_global->zone[++(table_global->top_zone)] = table_global->top_list + 1;

    // '{'
    if (strcmp(hold, "LBrace") == 0 ) {
        if (mode) { fprintf(fp_out, "{\n"); }
    } else {
        exit(2);   // 语法错误
    }
    memset(hold, '\0', sizeof(hold));
    fscanf(fp_in, "%s", hold);
    
    while (isBlockItemBegin(hold)) {
        // BlockItem
        analyseBlockItem(fp_in, fp_out);
    }
    
    // '}'
    if (strcmp(hold, "RBrace") == 0 ) {
        if (mode) { fprintf(fp_out, "}"); }
    } else {
        exit(2);   // 语法错误
    }
    memset(hold, '\0', sizeof(hold));
    fscanf(fp_in, "%s", hold);

    // 符号表作用域更新
    table_global->top_list = table_global->zone[(table_global->top_zone)] - 1;
    table_global->top_zone--;
}

void analyseFuncBlock(FILE *fp_in, FILE *fp_out, Ident *function) {
    // '{'
    if (strcmp(hold, "LBrace") == 0 ) {
       fprintf(fp_out, " {\n");
    } else {
        exit(2);   // 语法错误
    }
    memset(hold, '\0', sizeof(hold));
    fscanf(fp_in, "%s", hold);
    
    // LLVM--函数参数初始化
    for (int i=0; i<function->param_num; i++) {
        Ident *param = function->params[i];
        if (param->dimension == 0) {
            fprintf(fp_out, "\t%%x%d = alloca i32\n", ++register_cnt);
            fprintf(fp_out, "\tstore i32 %%x%d, i32* %%x%d\n", param->address, register_cnt);
            param->address = register_cnt;
        } else if (param->dimension == 1) {
            fprintf(fp_out, "\t%%x%d = alloca i32*\n", ++register_cnt);
            fprintf(fp_out, "\tstore i32* %%x%d, i32* * %%x%d\n", param->address, register_cnt);
            param->address = register_cnt;
        } else {
            fprintf(fp_out, "\t%%x%d = alloca ", ++register_cnt);
            printArrayScaleLLVM(fp_out, param, 1);
            fprintf(fp_out, "*\n\tstore ");
            printArrayScaleLLVM(fp_out, param, 1);
            fprintf(fp_out, "* %%x%d, ", param->address);
            printArrayScaleLLVM(fp_out, param, 1);
            fprintf(fp_out, "* * %%x%d\n", register_cnt);
            param->address = register_cnt;
        }
    }

    // BlockItem
    while (isBlockItemBegin(hold)) {
        // BlockItem
        analyseBlockItem(fp_in, fp_out);
    }

    // LLVM -- 默认返回值
    if (strcmp(function->type, "Void") == 0) {
        fprintf(fp_out, "\tret void\n");
    }
    if (strcmp(function->type, "Int") == 0) {
        fprintf(fp_out, "\tret i32 0\n");
    }
    
    // '}'
    if (strcmp(hold, "RBrace") == 0 ) {
        fprintf(fp_out, "}\n");
    } else {
        exit(2);   // 语法错误
    }
    memset(hold, '\0', sizeof(hold));
    fscanf(fp_in, "%s", hold);
}

void analyseBlockItem(FILE *fp_in, FILE *fp_out) {
    // Decl
    if (isDeclBegin(hold)) {
        analyseDecl(fp_in, fp_out);
    }

    // Stmt
    else {
        analyseStmt(fp_in, fp_out);
    }
}

void analyseDecl(FILE *fp_in, FILE *fp_out) {
    // ConstDecl
    if (strcmp(hold, "Const") == 0) {
        memset(hold, '\0', sizeof(hold));
        fscanf(fp_in, "%s", hold);

        // Btype
        if (strcmp(hold, "Int") != 0) {
            exit(2);   // 语法错误
        }
        memset(hold, '\0', sizeof(hold));
        fscanf(fp_in, "%s", hold);

        // ConstDef
        if (isIdentBegin(hold)) {
            analyseConstDef(fp_in, fp_out);
        } else {
            exit(2);   // 语法错误
        }

        while (strcmp(hold, "Comma") == 0) {
            memset(hold, '\0', sizeof(hold));
            fscanf(fp_in, "%s", hold);
            if (isIdentBegin(hold)) {
                analyseConstDef(fp_in, fp_out);
            } else {
                exit(2);   // 语法错误
            }
        }

        // ';'
        if (strcmp(hold, "Semicolon") != 0) {
            exit(2);   // 语法错误
        }
        memset(hold, '\0', sizeof(hold));
        fscanf(fp_in, "%s", hold);
    }

    // VarDecl
    else {
        // Btype
        if (strcmp(hold, "Int") != 0) {
            exit(2);   // 语法错误
        }
        memset(hold, '\0', sizeof(hold));
        fscanf(fp_in, "%s", hold);

        // VarDef
        if (isIdentBegin(hold)) {
            analyseVarDef(fp_in, fp_out);
        } else {
            exit(2);   // 语法错误
        }

        while (strcmp(hold, "Comma") == 0) {
            memset(hold, '\0', sizeof(hold));
            fscanf(fp_in, "%s", hold);
            if (isIdentBegin(hold)) {
                analyseVarDef(fp_in, fp_out);
            } else {
                exit(2);   // 语法错误
            }
        }

        // ';'
        if (strcmp(hold, "Semicolon") != 0) {
            exit(2);   // 语法错误
        }
        memset(hold, '\0', sizeof(hold));
        fscanf(fp_in, "%s", hold);
    }
}

void analyseConstDef(FILE *fp_in, FILE *fp_out) {
    // Ident
    slice(hold, 6, strlen(hold)-2);
    if (isInTable(hold, table_global)) {        // 符号表操作
        printf("Ident exist!\n");
        exit(3);    // 语义错误
    }

    Ident *ident = (Ident *)malloc(sizeof(Ident));
    strcpy(ident->name, hold);
    strcpy(ident->type, "int");
    ident->value = 0;
    ident->def = 1;
    ident->dimension = 0;
    insertItem(ident, table_global);

    memset(hold, '\0', sizeof(hold));
    fscanf(fp_in, "%s", hold);

    // '[' 数组
    while (strcmp(hold, "LBracket") == 0) {
        memset(hold, '\0', sizeof(hold));
        fscanf(fp_in, "%s", hold);
        Inter_var *index = analyseExp(fp_in, fp_out, 1);

        // index>0 语义检查
        if (index->value <= 0) {
            printf("Wrong array length!\n");
            exit(1);    // 语义错误
        } else {
            ident->index[ident->dimension++] = index->value;
        }

        if (strcmp(hold, "RBracket") != 0) {
            printf("']' missed!/n");
            exit(1);    // 语法错误
        }
        memset(hold, '\0', sizeof(hold));
        fscanf(fp_in, "%s", hold);
    }

    // 声明存址
    if (ident->dimension != 0) {
        // 声明数组记录地址
        ident->address = ++register_cnt;
        fprintf(fp_out, "\t%%x%d = alloca ", ident->address);
        printArrayScaleLLVM(fp_out, ident, 0);
        fprintf(fp_out, "\n");
        for (int i=0; i<ident->dimension; i++) {
            int temp_reg = register_cnt;
            fprintf(fp_out, "\t%%x%d = getelementptr ", ++register_cnt);
            printArrayScaleLLVM(fp_out, ident, i);
            fprintf(fp_out, ", ");
            printArrayScaleLLVM(fp_out, ident, i);
            fprintf(fp_out, "* %%x%d, i32 0, i32 0\n", temp_reg);
        }
        fprintf(fp_out, "\tcall void @memset(i32* %%x%d, i32 0, i32 %d)\n", register_cnt, getArrayByte(ident));
    }

    // '='
    if (strcmp(hold, "Assign") != 0) {
        printf("Const def error!\n");
        exit(2);    // 语法错误
    }
    memset(hold, '\0', sizeof(hold));
    fscanf(fp_in, "%s", hold);

    int loc = 0;
    Inter_var *result = analyseLocalConstInitVal(fp_in, fp_out, ident, 0, &loc);

    // 常量
    if (result != NULL) {
        ident->address = -1;
        ident->value = result->value;        
    }
}

void analyseVarDef(FILE *fp_in, FILE *fp_out) {
    // Ident
    slice(hold, 6, strlen(hold)-2);
    if (isInTable(hold, table_global)) {        // 符号表操作
        printf("Ident exist!\n");
        exit(3);    // 语义错误
    }

    Ident *ident = (Ident *)malloc(sizeof(Ident));
    strcpy(ident->name, hold);
    strcpy(ident->type, "int");
    ident->value = 0;
    ident->def = 0;
    ident->dimension = 0;
    insertItem(ident, table_global);

    memset(hold, '\0', sizeof(hold));
    fscanf(fp_in, "%s", hold);

    // '[' 数组
    while (strcmp(hold, "LBracket") == 0) {
        memset(hold, '\0', sizeof(hold));
        fscanf(fp_in, "%s", hold);
        Inter_var *index = analyseExp(fp_in, fp_out, 1);

        // index>0 语义检查
        if (index->value <= 0) {
            printf("Wrong array length!\n");
            exit(1);    // 语义错误
        } else {
            ident->index[ident->dimension++] = index->value;
        }

        if (strcmp(hold, "RBracket") != 0) {
            printf("']' missed!/n");
            exit(1);    // 语法错误
        }
        memset(hold, '\0', sizeof(hold));
        fscanf(fp_in, "%s", hold);
    }

    // 声明存址
    if (ident->dimension == 0) {
        // 声明变量保存地址
        ident->address = ++register_cnt;
        fprintf(fp_out, "\t%%x%d = alloca i32\n", ident->address);
    } 
    else {
        // 声明数组记录地址
        ident->address = ++register_cnt;
        fprintf(fp_out, "\t%%x%d = alloca ", ident->address);
        printArrayScaleLLVM(fp_out, ident, 0);
        fprintf(fp_out, "\n");
        for (int i=0; i<ident->dimension; i++) {
            int temp_reg = register_cnt;
            fprintf(fp_out, "\t%%x%d = getelementptr ", ++register_cnt);
            printArrayScaleLLVM(fp_out, ident, i);
            fprintf(fp_out, ", ");
            printArrayScaleLLVM(fp_out, ident, i);
            fprintf(fp_out, "* %%x%d, i32 0, i32 0\n", temp_reg);
        }
        fprintf(fp_out, "\tcall void @memset(i32* %%x%d, i32 0, i32 %d)\n", register_cnt, getArrayByte(ident));
    }

    if (strcmp(hold, "Assign") == 0) {
        memset(hold, '\0', sizeof(hold));
        fscanf(fp_in, "%s", hold);

        int loc = 0;
        Inter_var *result = analyseInitVal(fp_in, fp_out, ident, 0, &loc);

        if (result != NULL) {
            ident->value = result->value;
            if (result->reg == -1) { fprintf(fp_out, "\tstore i32 %d, i32* %%x%d\n", result->value, ident->address);}
            else { fprintf(fp_out, "\tstore i32 %%x%d, i32* %%x%d\n", result->reg, ident->address); }        
        }
    }
}

Inter_var *analyseInitVal(FILE *fp_in, FILE *fp_out, Ident *ident, int depth, int *loc) {
    // '{'
    if (strcmp(hold, "LBrace") == 0) {
        memset(hold, '\0', sizeof(hold));
        fscanf(fp_in, "%s", hold);

        if (strcmp(hold, "RBrace") != 0) {
            Inter_var *result = analyseInitVal(fp_in, fp_out, ident, depth+1, loc);
            
            // 层第一个值
            if (result != NULL) { 
                fprintf(fp_out, "\t%%x%d = getelementptr i32, i32* %%x%d, i32 %d\n", ++register_cnt, ident->address+ident->dimension, (*loc)++);
                if (result->reg == -1) {
                    fprintf(fp_out, "\tstore i32 %d, i32* %%x%d\n", result->value, register_cnt);
                } else {
                    fprintf(fp_out, "\tstore i32 %%x%d, i32* %%x%d\n", result->reg, register_cnt);
                }
            }

            int cnt = 1;
            // ','
            while (strcmp(hold, "Comma") == 0 || cnt < ident->index[depth]) {
                if (strcmp(hold, "Comma") == 0) {
                    memset(hold, '\0', sizeof(hold));
                    fscanf(fp_in, "%s", hold);
                    Inter_var *result = analyseInitVal(fp_in, fp_out, ident, depth+1, loc);
                    if (result != NULL) { 
                        fprintf(fp_out, "\t%%x%d = getelementptr i32, i32* %%x%d, i32 %d\n", ++register_cnt, ident->address+ident->dimension, (*loc)++);
                        if (result->reg == -1) {
                            fprintf(fp_out, "\tstore i32 %d, i32* %%x%d\n", result->value, register_cnt);
                        } else {
                            fprintf(fp_out, "\tstore i32 %%x%d, i32* %%x%d\n", result->reg, register_cnt);
                        }
                    }
                }
                else {
                    // 补充loc
                    (*loc)++;
                }     
                cnt++;
            }
        } else {
            // 空括号补充loc
            *loc += getBlankLoc(ident, depth);
        }

        if (strcmp(hold, "RBrace") != 0 ) {
            printf("Array decl no RBrace!\n");
            exit(2);    // 语法错误
        }

        memset(hold, '\0', sizeof(hold));
        fscanf(fp_in, "%s", hold);
        return NULL;
    }

    // Exp
    else {
        return analyseExp(fp_in, fp_out, 0);
    }
}

Inter_var *analyseLocalConstInitVal(FILE *fp_in, FILE *fp_out, Ident *ident, int depth, int *loc) {
    // '{'
    if (strcmp(hold, "LBrace") == 0) {
        memset(hold, '\0', sizeof(hold));
        fscanf(fp_in, "%s", hold);

        if (strcmp(hold, "RBrace") != 0) {
            Inter_var *result = analyseLocalConstInitVal(fp_in, fp_out, ident, depth+1, loc);
            
            // 层第一个值
            if (result != NULL) { 
                fprintf(fp_out, "\t%%x%d = getelementptr i32, i32* %%x%d, i32 %d\n", ++register_cnt, ident->address+ident->dimension, (*loc)++);
                if (result->reg == -1) {
                    fprintf(fp_out, "\tstore i32 %d, i32* %%x%d\n", result->value, register_cnt);
                } else {
                    fprintf(fp_out, "\tstore i32 %%x%d, i32* %%x%d\n", result->reg, register_cnt);
                }
            }

            int cnt = 1;
            // ','
            while (strcmp(hold, "Comma") == 0 || cnt < ident->index[depth]) {
                if (strcmp(hold, "Comma") == 0) {
                    memset(hold, '\0', sizeof(hold));
                    fscanf(fp_in, "%s", hold);
                    Inter_var *result = analyseLocalConstInitVal(fp_in, fp_out, ident, depth+1, loc);
                    if (result != NULL) { 
                        fprintf(fp_out, "\t%%x%d = getelementptr i32, i32* %%x%d, i32 %d\n", ++register_cnt, ident->address+ident->dimension, (*loc)++);
                        if (result->reg == -1) {
                            fprintf(fp_out, "\tstore i32 %d, i32* %%x%d\n", result->value, register_cnt);
                        } else {
                            fprintf(fp_out, "\tstore i32 %%x%d, i32* %%x%d\n", result->reg, register_cnt);
                        }
                    }
                }
                else {
                    // 补充loc
                    (*loc)++;
                }     
                cnt++;
            }
        } else {
            // 空括号补充loc
            *loc += getBlankLoc(ident, depth);
        }

        if (strcmp(hold, "RBrace") != 0 ) {
            printf("Array decl no RBrace!\n");
            exit(2);    // 语法错误
        }

        memset(hold, '\0', sizeof(hold));
        fscanf(fp_in, "%s", hold);
        return NULL;
    }

    // Exp
    else {
        return analyseExp(fp_in, fp_out, 1);
    }
}

void analyseStmt(FILE *fp_in, FILE *fp_out) {
    // ;
    if (strcmp(hold, "Semicolon") == 0) {
        memset(hold, '\0', sizeof(hold));
        fscanf(fp_in, "%s", hold);
        return;
    }
    // return
    else if (strcmp(hold, "Return") == 0) {
        memset(hold, '\0', sizeof(hold));
        fscanf(fp_in, "%s", hold);
        // void
        if (strcmp(hold, "Semicolon") == 0) {
            fprintf(fp_out, "\tret void\n");
        }
        // int
        else {
            // Exp
            Inter_var *result = analyseExp(fp_in, fp_out, 0);
            if (result->reg == -1) {
                fprintf(fp_out, "\tret i32 %d\n", result->value);
            } else {
                fprintf(fp_out, "\tret i32 %%x%d\n", result->reg);
            }
        }
    } 
    // Func
    else if (isFuncBegin(hold)) {
        char temp[MAXLEN];
        strcpy(temp, hold);
        memset(hold, '\0', sizeof(hold));
        fscanf(fp_in, "%s", hold);
        Inter_var *result = analyseFuction(fp_in, fp_out, temp);
        memset(hold, '\0', sizeof(hold));
        fscanf(fp_in, "%s", hold);
    }
    // Ident
    else if (isIdentBegin(hold)) {
        slice(hold, 6, strlen(hold)-2);
        Ident *ident = findGlobalItem(hold, table_global);
        if (ident == NULL) {
            printf("Ident must be declared!\n");
            exit(3);    // 语义错误
        }
        if (ident->def == 1) {
            printf("Must be Var!\n");
            exit(3);    // 语义错误
        } 
        memset(hold, '\0', sizeof(hold));
        fscanf(fp_in, "%s", hold);

        // 数组相关变量
        int array_reg = 0;
        
        // 数组检查
        if (ident->dimension > 0) {
            // 依据下标获得地址
            Inter_var *indexes[MAXLEN>>6];
            for (int i=0; i<ident->dimension; i++) {
                // '['
                if (strcmp(hold, "LBracket") != 0) {
                    printf("Wrong dimension!\n");
                    exit(3);    // 语义错误
                }
                memset(hold, '\0', sizeof(hold));
                fscanf(fp_in, "%s", hold);

                // Exp
                Inter_var *index = analyseExp(fp_in, fp_out, 0);
                indexes[i] = index;
                
                // ']'
                if (strcmp(hold, "RBracket") != 0) {
                    printf("']' missed!/n");
                    exit(1);    // 语法错误
                }
                memset(hold, '\0', sizeof(hold));
                fscanf(fp_in, "%s", hold);
            }

            // LLVM
            // 参数情况
            if (ident->def == 5) {
                // load
                if (ident->dimension == 1) {
                    fprintf(fp_out, "\t%%x%d = load i32* , i32* * %%x%d\n", ++register_cnt, ident->address);
                } else {
                    fprintf(fp_out, "\t%%x%d = load ", ++register_cnt);
                    printArrayScaleLLVM(fp_out, ident, 1);
                    fprintf(fp_out, "*, ");
                    printArrayScaleLLVM(fp_out, ident, 1);
                    fprintf(fp_out, "* * %%x%d\n", ident->address);
                }
                array_reg = register_cnt;
                // getelementptr
                if (ident->dimension == 1) {
                    if (indexes[0]->reg == -1) {
                        fprintf(fp_out, "\t%%x%d = getelementptr i32, i32* %%x%d, i32 %d\n", ++register_cnt, array_reg, indexes[0]->value);
                    } else {
                        fprintf(fp_out, "\t%%x%d = getelementptr i32, i32* %%x%d, i32 %%x%d\n", ++register_cnt, array_reg, indexes[0]->reg);
                    }
                    array_reg = register_cnt;
                } else {
                    fprintf(fp_out, "\t%%x%d = getelementptr ", ++register_cnt);
                    printArrayScaleLLVM(fp_out, ident, 1);
                    fprintf(fp_out, ", ");
                    printArrayScaleLLVM(fp_out, ident, 1);
                    fprintf(fp_out, "* %%x%d, i32 0\n", array_reg);
                    array_reg = register_cnt;

                    // 逐维数计算索引
                    fprintf(fp_out, "\t%%x%d = add i32 0, 0\n", ++register_cnt);
                    int reg_total = register_cnt;
                    for (int i=1; i<ident->dimension; i++) {
                        // 维偏移
                        if (indexes[i-1]->reg == -1) {
                            fprintf(fp_out, "\t%%x%d = mul i32 %d, %d\n", ++register_cnt, indexes[i-1]->value, getBlankLoc(ident, i)); 
                        } else {
                            fprintf(fp_out, "\t%%x%d = mul i32 %%x%d, %d\n", ++register_cnt, indexes[i-1]->value, getBlankLoc(ident, i)); 
                        }
                        // 偏移量相加
                        fprintf(fp_out, "\t%%x%d = add i32 %%x%d, %%x%d\n", register_cnt+1, reg_total, register_cnt);
                        register_cnt++;
                        reg_total = register_cnt;
                    }
                    // 计算最后偏移
                    if (indexes[ident->dimension-1]->reg == -1) {
                        fprintf(fp_out, "\t%%x%d = add i32 %%x%d, %d\n", ++register_cnt, reg_total, indexes[ident->dimension-1]->value);
                    } else {
                        fprintf(fp_out, "\t%%x%d = add i32 %%x%d, %%x%d\n", ++register_cnt, reg_total, indexes[ident->dimension-1]->reg);
                    }
                    reg_total = register_cnt;

                    // 根据索引赋值
                    fprintf(fp_out, "\t%%x%d = getelementptr ", ++register_cnt);
                    printArrayScaleLLVM(fp_out, ident, 1);
                    fprintf(fp_out, ", ");
                    printArrayScaleLLVM(fp_out, ident, 1);
                    // 多维修改此处 i32 0 若干
                    fprintf(fp_out, "* %%x%d, i32 0, i32 %%x%d\n", array_reg, reg_total);
                    fprintf(fp_out, "\t%%x%d = load i32, i32* %%x%d\n", register_cnt+1, register_cnt);
                    array_reg = ++register_cnt;
                }
            }
            // 非参数情况 
            else {
                fprintf(fp_out, "\t%%x%d = getelementptr ", ++register_cnt);
                printArrayScaleLLVM(fp_out, ident, 0);
                fprintf(fp_out, ", ");
                printArrayScaleLLVM(fp_out, ident, 0);
                if (ident->def == 3 || ident->def == 4) {
                    fprintf(fp_out, "* @%s, i32 0", ident->name);
                } else {
                    fprintf(fp_out, "* %%x%d, i32 0", ident->address);
                }
                for (int i=0; i<ident->dimension; i++) {
                    if (indexes[i]->reg == -1) {
                        fprintf(fp_out, ", i32 %d", indexes[i]->value);
                    } else {
                        fprintf(fp_out, ", i32 %%x%d", indexes[i]->reg);
                    }
                }
                fprintf(fp_out, "\n");
                array_reg = register_cnt;
            }
        }

        // 判断空表达式
        int flag_blank = 0;

        // '='
        if (strcmp(hold, "Assign") != 0) {
            while (isExpBegin(hold)) {
                memset(hold, '\0', sizeof(hold));
                fscanf(fp_in, "%s", hold);
            }
            if (strcmp(hold, "Semicolon") != 0) {
                printf("Unknown exp signal!\n");
                exit(2);   // 语法错误
            }
            flag_blank = 1;
        } else {
            memset(hold, '\0', sizeof(hold));
            fscanf(fp_in, "%s", hold);
        }

        if (!flag_blank) {
            // Exp
            Inter_var *result = analyseExp(fp_in, fp_out, 0);
            ident->value = result->value;
            // 数组
            if (ident->dimension > 0) {
                if (result->reg == -1) { fprintf(fp_out, "\tstore i32 %d, i32* %%x%d\n", result->value, array_reg); }
                else { fprintf(fp_out, "\tstore i32 %%x%d, i32* %%x%d\n", result->reg, array_reg); }
            }
            // 全局变量
            else if (ident->def == 3) {
                if (result->reg == -1) { fprintf(fp_out, "\tstore i32 %d, i32* @%s\n", result->value, ident->name);}
                else { fprintf(fp_out, "\tstore i32 %%x%d, i32* @%s\n", result->reg, ident->name); }
            }
            // 其他 
            else {
                if (result->reg == -1) { fprintf(fp_out, "\tstore i32 %d, i32* %%x%d\n", result->value, ident->address);}
                else { fprintf(fp_out, "\tstore i32 %%x%d, i32* %%x%d\n", result->reg, ident->address); }
            }
        }
    }
    // Block
    else if (strcmp(hold, "LBrace") == 0) {
        analyseBlock(fp_in, fp_out, 0);
        return;
    }
    // If
    else if (strcmp(hold, "If") == 0) {
        memset(hold, '\0', sizeof(hold));
        fscanf(fp_in, "%s", hold);

        // '('
        if (strcmp(hold, "LPar") != 0) {
            exit(2);    // 语法错误
        }
        memset(hold, '\0', sizeof(hold));
        fscanf(fp_in, "%s", hold);
        
        // cond
        Inter_var *result = analyseCond(fp_in, fp_out);
        fprintf(fp_out, "\tbr i1 %%x%d, label %%x%d, label %%x%d\n", result->reg_i1, register_cnt+1, register_cnt+2);

        // ')'
        if (strcmp(hold, "RPar") != 0) {
            exit(2);    // 语法错误
        }
        memset(hold, '\0', sizeof(hold));
        fscanf(fp_in, "%s", hold);

        int begin_if = ++register_cnt;
        int begin_else = ++register_cnt;
        int end = ++register_cnt;
        
        // Stmt
        fprintf(fp_out, "\nx%d:\n", begin_if);
        analyseStmt(fp_in, fp_out);
        fprintf(fp_out, "\tbr label %%x%d\n", end);
        
        // Else
        if (strcmp(hold, "Else") == 0) {
            memset(hold, '\0', sizeof(hold));
            fscanf(fp_in, "%s", hold);

            // Stmt
            fprintf(fp_out, "\nx%d:\n", begin_else);
            analyseStmt(fp_in, fp_out);
            fprintf(fp_out, "\tbr label %%x%d\n", end);

        } else {
            fprintf(fp_out, "\nx%d:\n", begin_else);
            fprintf(fp_out, "\tbr label %%x%d\n", end);
        }
        fprintf(fp_out, "\nx%d:\n", end);
        return;
    }
    // While
    else if (strcmp(hold, "While") == 0) {
        memset(hold, '\0', sizeof(hold));
        fscanf(fp_in, "%s", hold);

        // '('
        if (strcmp(hold, "LPar") != 0) {
            exit(2);    // 语法错误
        }
        memset(hold, '\0', sizeof(hold));
        fscanf(fp_in, "%s", hold);

        // cond
        int begin_cond = ++register_cnt;
        fprintf(fp_out, "\tbr label %%x%d\n", begin_cond);
        fprintf(fp_out, "\nx%d:\n", begin_cond);
        Inter_var *result = analyseCond(fp_in, fp_out);
        int begin_while = ++register_cnt;
        int end_while = ++register_cnt;
        fprintf(fp_out, "\tbr i1 %%x%d, label %%x%d, label %%x%d\n", result->reg_i1, begin_while, end_while);

        // ')'
        if (strcmp(hold, "RPar") != 0) {
            exit(2);    // 语法错误
        }
        memset(hold, '\0', sizeof(hold));
        fscanf(fp_in, "%s", hold);

        // Stmt
        fprintf(fp_out, "\nx%d:\n", begin_while);
        int where = analyseWhileStmt(fp_in, fp_out, begin_cond, end_while);
        fprintf(fp_out, "\tbr label %%x%d\n", begin_cond);
        fprintf(fp_out, "\nx%d:\n", end_while);
        return;
    }
    // Exp
    else {
        Inter_var *result = analyseExp(fp_in, fp_out, 0);
    }

    // ';'
    if (strcmp(hold, "Semicolon") != 0) {
        exit(2);   // 语法错误
    }
    memset(hold, '\0', sizeof(hold));
    fscanf(fp_in, "%s", hold);
}

int analyseWhileStmt(FILE *fp_in, FILE *fp_out, int to_continue, int to_break) {
    // ;
    if (strcmp(hold, "Semicolon") == 0) {
        memset(hold, '\0', sizeof(hold));
        fscanf(fp_in, "%s", hold);
        return 0;
    }
    // return
    else if (strcmp(hold, "Return") == 0) {
        memset(hold, '\0', sizeof(hold));
        fscanf(fp_in, "%s", hold);

        // void
        if (strcmp(hold, "Semicolon") == 0) {
            fprintf(fp_out, "\tret void\n");
        }
        // int
        else {
            // Exp
            Inter_var *result = analyseExp(fp_in, fp_out, 0);
            if (result->reg == -1) {
                fprintf(fp_out, "\tret i32 %d\n", result->value);
            } else {
                fprintf(fp_out, "\tret i32 %%x%d\n", result->reg);
            }
        }
    } 
    // Func
    else if (isFuncBegin(hold)) {
        char temp[MAXLEN];
        strcpy(temp, hold);
        memset(hold, '\0', sizeof(hold));
        fscanf(fp_in, "%s", hold);
        Inter_var *result = analyseFuction(fp_in, fp_out, temp);
        memset(hold, '\0', sizeof(hold));
        fscanf(fp_in, "%s", hold);
    }
    // Ident
    else if (isIdentBegin(hold)) {
        slice(hold, 6, strlen(hold)-2);
        Ident *ident = findGlobalItem(hold, table_global);
        if (ident == NULL) {
            printf("Must be declared!\n");
            exit(3);    // 语义错误
        }
        if (ident->def == 1) {
            printf("Must be Var!\n");
            exit(3);    // 语义错误
        } 
        memset(hold, '\0', sizeof(hold));
        fscanf(fp_in, "%s", hold);

        // 数组相关变量
        int array_reg = 0;

        // 数组检查
        if (ident->dimension > 0) {
            // 依据下标获得地址
            Inter_var *indexes[MAXLEN>>6];
            for (int i=0; i<ident->dimension; i++) {
                // '['
                if (strcmp(hold, "LBracket") != 0) {
                    printf("Wrong dimension!\n");
                    exit(3);    // 语义错误
                }
                memset(hold, '\0', sizeof(hold));
                fscanf(fp_in, "%s", hold);

                // Exp
                Inter_var *index = analyseExp(fp_in, fp_out, 0);
                indexes[i] = index;
                
                // ']'
                if (strcmp(hold, "RBracket") != 0) {
                    printf("']' missed!/n");
                    exit(1);    // 语法错误
                }
                memset(hold, '\0', sizeof(hold));
                fscanf(fp_in, "%s", hold);
            }

            // LLVM
            // 参数情况
            if (ident->def == 5) {
                // load
                if (ident->dimension == 1) {
                    fprintf(fp_out, "\t%%x%d = load i32* , i32* * %%x%d\n", ++register_cnt, ident->address);
                } else {
                    fprintf(fp_out, "\t%%x%d = load ", ++register_cnt);
                    printArrayScaleLLVM(fp_out, ident, 1);
                    fprintf(fp_out, "*, ");
                    printArrayScaleLLVM(fp_out, ident, 1);
                    fprintf(fp_out, "* * %%x%d\n", ident->address);
                }
                array_reg = register_cnt;
                // getelementptr
                if (ident->dimension == 1) {
                    if (indexes[0]->reg == -1) {
                        fprintf(fp_out, "\t%%x%d = getelementptr i32, i32* %%x%d, i32 %d\n", ++register_cnt, array_reg, indexes[0]->value);
                    } else {
                        fprintf(fp_out, "\t%%x%d = getelementptr i32, i32* %%x%d, i32 %%x%d\n", ++register_cnt, array_reg, indexes[0]->reg);
                    }
                    array_reg = register_cnt;
                } else {
                    fprintf(fp_out, "\t%%x%d = getelementptr ", ++register_cnt);
                    printArrayScaleLLVM(fp_out, ident, 1);
                    fprintf(fp_out, ", ");
                    printArrayScaleLLVM(fp_out, ident, 1);
                    fprintf(fp_out, "* %%x%d, i32 0\n", array_reg);
                    array_reg = register_cnt;

                    // 逐维数计算索引
                    fprintf(fp_out, "\t%%x%d = add i32 0, 0\n", ++register_cnt);
                    int reg_total = register_cnt;
                    for (int i=1; i<ident->dimension; i++) {
                        // 维偏移
                        if (indexes[i-1]->reg == -1) {
                            fprintf(fp_out, "\t%%x%d = mul i32 %d, %d\n", ++register_cnt, indexes[i-1]->value, getBlankLoc(ident, i)); 
                        } else {
                            fprintf(fp_out, "\t%%x%d = mul i32 %%x%d, %d\n", ++register_cnt, indexes[i-1]->value, getBlankLoc(ident, i)); 
                        }
                        // 偏移量相加
                        fprintf(fp_out, "\t%%x%d = add i32 %%x%d, %%x%d\n", register_cnt+1, reg_total, register_cnt);
                        register_cnt++;
                        reg_total = register_cnt;
                    }
                    // 计算最后偏移
                    if (indexes[ident->dimension-1]->reg == -1) {
                        fprintf(fp_out, "\t%%x%d = add i32 %%x%d, %d\n", ++register_cnt, reg_total, indexes[ident->dimension-1]->value);
                    } else {
                        fprintf(fp_out, "\t%%x%d = add i32 %%x%d, %%x%d\n", ++register_cnt, reg_total, indexes[ident->dimension-1]->reg);
                    }
                    reg_total = register_cnt;

                    // 根据索引赋值
                    fprintf(fp_out, "\t%%x%d = getelementptr ", ++register_cnt);
                    printArrayScaleLLVM(fp_out, ident, 1);
                    fprintf(fp_out, ", ");
                    printArrayScaleLLVM(fp_out, ident, 1);
                    // 多维修改此处 i32 0 若干
                    fprintf(fp_out, "* %%x%d, i32 0, i32 %%x%d\n", array_reg, reg_total);
                    fprintf(fp_out, "\t%%x%d = load i32, i32* %%x%d\n", register_cnt+1, register_cnt);
                    array_reg = ++register_cnt;
                }
            }
            // 非参数情况
            else {
                fprintf(fp_out, "\t%%x%d = getelementptr ", ++register_cnt);
                printArrayScaleLLVM(fp_out, ident, 0);
                fprintf(fp_out, ", ");
                printArrayScaleLLVM(fp_out, ident, 0);
                if (ident->def == 3 || ident->def == 4) {
                    fprintf(fp_out, "* @%s, i32 0", ident->name);
                } else {
                    fprintf(fp_out, "* %%x%d, i32 0", ident->address);
                }
                for (int i=0; i<ident->dimension; i++) {
                    if (indexes[i]->reg == -1) {
                        fprintf(fp_out, ", i32 %d", indexes[i]->value);
                    } else {
                        fprintf(fp_out, ", i32 %%x%d", indexes[i]->reg);
                    }
                }
                fprintf(fp_out, "\n");
                array_reg = register_cnt;
            }
        }
        
        // 判断空表达式
        int flag_blank = 0;

        // '='
        if (strcmp(hold, "Assign") != 0) {
            while (isExpBegin(hold)) {
                memset(hold, '\0', sizeof(hold));
                fscanf(fp_in, "%s", hold);
            }
            if (strcmp(hold, "Semicolon") != 0) {
                printf("Unknown exp signal!\n");
                exit(2);   // 语法错误
            }
            flag_blank = 1;
        } else {
            memset(hold, '\0', sizeof(hold));
            fscanf(fp_in, "%s", hold);
        }

        if (!flag_blank) {
            // Exp
            Inter_var *result = analyseExp(fp_in, fp_out, 0);
            ident->value = result->value;
            // 数组
            if (ident->dimension > 0) {
                if (result->reg == -1) { fprintf(fp_out, "\tstore i32 %d, i32* %%x%d\n", result->value, array_reg); }
                else { fprintf(fp_out, "\tstore i32 %%x%d, i32* %%x%d\n", result->reg, array_reg); }
            }
            // 全局变量
            else if (ident->def == 3) {
                if (result->reg == -1) { fprintf(fp_out, "\tstore i32 %d, i32* @%s\n", result->value, ident->name);}
                else { fprintf(fp_out, "\tstore i32 %%x%d, i32* @%s\n", result->reg, ident->name); }
            }
            // 其他 
            else {
                if (result->reg == -1) { fprintf(fp_out, "\tstore i32 %d, i32* %%x%d\n", result->value, ident->address);}
                else { fprintf(fp_out, "\tstore i32 %%x%d, i32* %%x%d\n", result->reg, ident->address); }
            }
        }
    }
    // Block
    else if (strcmp(hold, "LBrace") == 0) {
        analyseWhileBlock(fp_in, fp_out, to_continue, to_break);
        return 0;
    }
    // If
    else if (strcmp(hold, "If") == 0) {
        memset(hold, '\0', sizeof(hold));
        fscanf(fp_in, "%s", hold);

        // '('
        if (strcmp(hold, "LPar") != 0) {
            exit(2);    // 语法错误
        }
        memset(hold, '\0', sizeof(hold));
        fscanf(fp_in, "%s", hold);
        
        // cond
        Inter_var *result = analyseCond(fp_in, fp_out);
        fprintf(fp_out, "\tbr i1 %%x%d, label %%x%d, label %%x%d\n", result->reg_i1, register_cnt+1, register_cnt+2);

        // ')'
        if (strcmp(hold, "RPar") != 0) {
            exit(2);    // 语法错误
        }
        memset(hold, '\0', sizeof(hold));
        fscanf(fp_in, "%s", hold);

        int begin_if = ++register_cnt;
        int begin_else = ++register_cnt;
        int end = ++register_cnt;
        
        // Stmt
        fprintf(fp_out, "\nx%d:\n", begin_if);
        analyseWhileStmt(fp_in, fp_out, to_continue, to_break);
        fprintf(fp_out, "\tbr label %%x%d\n", end);
        
        // Else
        if (strcmp(hold, "Else") == 0) {
            memset(hold, '\0', sizeof(hold));
            fscanf(fp_in, "%s", hold);

            // Stmt
            fprintf(fp_out, "\nx%d:\n", begin_else);
            analyseWhileStmt(fp_in, fp_out, to_continue, to_break);
            fprintf(fp_out, "\tbr label %%x%d\n", end);

        } else {
            fprintf(fp_out, "\nx%d:\n", begin_else);
            fprintf(fp_out, "\tbr label %%x%d\n", end);
        }
        fprintf(fp_out, "\nx%d:\n", end);
        return 0;
    }
    // While
    else if (strcmp(hold, "While") == 0) {
        memset(hold, '\0', sizeof(hold));
        fscanf(fp_in, "%s", hold);

        // '('
        if (strcmp(hold, "LPar") != 0) {
            exit(2);    // 语法错误
        }
        memset(hold, '\0', sizeof(hold));
        fscanf(fp_in, "%s", hold);

        // cond
        int begin_cond = ++register_cnt;
        fprintf(fp_out, "\tbr label %%x%d\n", begin_cond);
        fprintf(fp_out, "\nx%d:\n", begin_cond);
        Inter_var *result = analyseCond(fp_in, fp_out);
        int begin_while = ++register_cnt;
        int end_while = ++register_cnt;
        fprintf(fp_out, "\tbr i1 %%x%d, label %%x%d, label %%x%d\n", result->reg_i1, begin_while, end_while);

        // ')'
        if (strcmp(hold, "RPar") != 0) {
            exit(2);    // 语法错误
        }
        memset(hold, '\0', sizeof(hold));
        fscanf(fp_in, "%s", hold);

        // Stmt
        fprintf(fp_out, "\nx%d:\n", begin_while);
        int where = analyseWhileStmt(fp_in, fp_out, begin_cond, end_while);
        fprintf(fp_out, "\tbr label %%x%d\n", begin_cond);
        fprintf(fp_out, "\nx%d:\n", end_while);
        return where;
    }
    // Continue
    else if (strcmp(hold, "Continue") == 0) {
        memset(hold, '\0', sizeof(hold));
        fscanf(fp_in, "%s", hold);
        if (strcmp(hold, "Semicolon") != 0) {
            exit(2);   // 语法错误
        }
        memset(hold, '\0', sizeof(hold));
        fscanf(fp_in, "%s", hold);
        fprintf(fp_out, "\tbr label %%x%d\n", to_continue);
        return 1;
    }
    // Break
    else if (strcmp(hold, "Break") == 0) {
        memset(hold, '\0', sizeof(hold));
        fscanf(fp_in, "%s", hold);
        if (strcmp(hold, "Semicolon") != 0) {
            exit(2);   // 语法错误
        }
        memset(hold, '\0', sizeof(hold));
        fscanf(fp_in, "%s", hold);
        fprintf(fp_out, "\tbr label %%x%d\n", to_break);
        return 2;
    }
    // Exp
    else {
        Inter_var *result = analyseExp(fp_in, fp_out, 0);
    }

    // ';'
    if (strcmp(hold, "Semicolon") != 0) {
        exit(2);   // 语法错误
    }
    memset(hold, '\0', sizeof(hold));
    fscanf(fp_in, "%s", hold);
    return 0;
}

void analyseWhileBlock(FILE *fp_in, FILE *fp_out, int to_continue, int to_break) {
    // 符号表作用域更新
    table_global->zone[++(table_global->top_zone)] = table_global->top_list + 1;

    // continue&break判别符
    int flag = 0;

    // '{'
    if (strcmp(hold, "LBrace") != 0 ) {
        exit(2);   // 语法错误
    }
    memset(hold, '\0', sizeof(hold));
    fscanf(fp_in, "%s", hold);
    
    while (isBlockItemBegin(hold)) {
        // BlockItem
        flag = analyseWhileBlockItem(fp_in, fp_out, to_continue, to_break);
    }
    
    // '}'
    if (strcmp(hold, "RBrace") != 0 ) {
        exit(2);   // 语法错误
    }
    memset(hold, '\0', sizeof(hold));
    fscanf(fp_in, "%s", hold);

    // 符号表作用域更新
    table_global->top_list = table_global->zone[(table_global->top_zone)] - 1;
    table_global->top_zone--;
}

int analyseWhileBlockItem(FILE *fp_in, FILE *fp_out, int to_continue, int to_break) {
    int flag = 0;

    // Decl
    if (isDeclBegin(hold)) {
        analyseDecl(fp_in, fp_out);
    }

    // Stmt
    else {
        flag = analyseWhileStmt(fp_in, fp_out, to_continue, to_break);
    }

    return flag;
}

Inter_var *analyseCond(FILE *fp_in, FILE *fp_out) {
    Inter_var *result = analyseLOrExp(fp_in, fp_out);
}

Inter_var *analyseLOrExp(FILE *fp_in, FILE *fp_out) {
    Inter_var *result = analyseLAndExp(fp_in, fp_out);

    while (strcmp(hold, "Or") == 0) {
        memset(hold, '\0', sizeof(hold));
        fscanf(fp_in, "%s", hold);
        Inter_var *result_temp = analyseLOrExp(fp_in, fp_out);

        // LLVM
        printCondLLVM(fp_out, "or", result, result_temp);
    }

    return result;
}

Inter_var *analyseLAndExp(FILE *fp_in, FILE *fp_out) {
    Inter_var *result = analyseEqExp(fp_in, fp_out);

    while (strcmp(hold, "And") == 0) {
        memset(hold, '\0', sizeof(hold));
        fscanf(fp_in, "%s", hold);
        Inter_var *result_temp = analyseLAndExp(fp_in, fp_out);

        // LLVM
        printCondLLVM(fp_out, "and", result, result_temp);
    }

    return result;
}

Inter_var *analyseEqExp(FILE *fp_in, FILE *fp_out) {
    Inter_var *result = analyseRelExp(fp_in, fp_out);

    while (strcmp(hold, "Eq") == 0 || strcmp(hold, "NotEq") == 0) {
        // 缓存
        char temp[MAXLEN];
        memset(temp, '\0', sizeof(temp));
        strcpy(temp, hold);

        // 递归
        memset(hold, '\0', sizeof(hold));
        fscanf(fp_in, "%s", hold);
        Inter_var *result_temp = analyseEqExp(fp_in, fp_out);

        // LLVM
        if (strcmp(temp, "Eq") == 0) {
            printCondLLVM(fp_out, "eq", result, result_temp);
        }
        if (strcmp(temp, "NotEq") == 0) {
            printCondLLVM(fp_out, "ne", result, result_temp);
        }
    }

    // 强制类型转换，向上层提供i1数据类型
    if (result->reg_i1 == -1) {
        if (result->reg == -1) {fprintf(fp_out, "\t%%x%d = icmp ne i32 %d, 0\n", ++register_cnt, result->value);}
        else {fprintf(fp_out, "\t%%x%d = icmp ne i32 %%x%d, 0\n", ++register_cnt, result->reg);}

        result->reg_i1 = register_cnt;
    }
    return result;
}

Inter_var *analyseRelExp(FILE *fp_in, FILE *fp_out) {
    Inter_var *result = analyseExp(fp_in, fp_out, 2);

    while (strcmp(hold, "Great") == 0 || strcmp(hold, "GreatEq") == 0 || strcmp(hold, "Less") == 0 || strcmp(hold, "LessEq") == 0) {
        // 缓存
        char temp[MAXLEN];
        memset(temp, '\0', sizeof(temp));
        strcpy(temp, hold);

        // 递归
        memset(hold, '\0', sizeof(hold));
        fscanf(fp_in, "%s", hold);
        Inter_var *result_temp = analyseRelExp(fp_in, fp_out);

        // LLVM
        if (strcmp(temp, "Great") == 0) {
            printCondLLVM(fp_out, "sgt", result, result_temp);
        }
        if (strcmp(temp, "GreatEq") == 0) {
            printCondLLVM(fp_out, "sge", result, result_temp);
        }
        if (strcmp(temp, "Less") == 0) {
            printCondLLVM(fp_out, "slt", result, result_temp);
        }
        if (strcmp(temp, "LessEq") == 0) {
            printCondLLVM(fp_out, "sle", result, result_temp);
        }
    }

    return result;
}

/* last read missed */
Inter_var *analyseFuction(FILE *fp_in, FILE *fp_out, char name[]) {
    slice(name, 6, strlen(name)-2);
    Ident *function = findGlobalItem(name, table_global);
    
    memset(hold, '\0', sizeof(hold));
    fscanf(fp_in, "%s", hold);

    // 逐参数读入
    Inter_var *func_params[MAXLEN>>6];
    for (int i=0; i<function->param_num; i++) {
        if (i != 0) {
            if (strcmp(hold, "Comma") != 0) {
                printf("Param missed!\n");
                exit(3);    // 语义错误
            }
            memset(hold, '\0', sizeof(hold));
            fscanf(fp_in, "%s", hold);
        }
        func_params[i] = analyseExp(fp_in, fp_out, 2);
    } 

    if (strcmp(hold, "RPar") != 0) {
        printf("Function no par!\n");
        exit(2);    // 语法错误
    }

    // LLVM
    if (strcmp(function->type, "Int") == 0) {
        fprintf(fp_out, "\t%%x%d = call i32 @%s(", ++register_cnt, function->name);
    } else {
        fprintf(fp_out, "\tcall void @%s(", function->name);
    }
    // 逐参数输出
    for (int i=0; i<function->param_num; i++) {
        // ','
        if (i != 0) {
            fprintf(fp_out, ", ");
        }
        if (function->params[i]->dimension == 0) {
            if (func_params[i]->reg == -1) { fprintf(fp_out, "i32 %d", func_params[i]->value); } 
            else { fprintf(fp_out, "i32 %%x%d", func_params[i]->reg); }
        } else if (function->params[i]->dimension == 1) {
            if (func_params[i]->reg == -1) { fprintf(fp_out, "i32* %d", func_params[i]->value); } 
            else { fprintf(fp_out, "i32* %%x%d", func_params[i]->reg); }
        } else {
            printArrayScaleLLVM(fp_out, function->params[i], 1);
            if (func_params[i]->reg == -1) { fprintf(fp_out, "* %d", func_params[i]->value); } 
            else { fprintf(fp_out, "* %%x%d", func_params[i]->reg); }
        }
    }
    fprintf(fp_out, ")\n");

    // 返回值
    if (strcmp(function->type, "Int") == 0) {
        Inter_var *result = (Inter_var *)malloc(sizeof(Inter_var));
        result->reg = register_cnt;
        result->value = 1;
        result->reg_i1 = -1;
        return result;
    } else {
        return NULL;
    }
}

Inter_var *analyseExp(FILE *fp_in, FILE *fp_out, int mode) {
    // 初始化
    enum operator operators[MAXLEN];
    int top_opt = -1;
    Inter_var vars[MAXLEN];
    int top_var = -1;
    memset(operators, 0, sizeof(operators));
    memset(vars, 0, sizeof(vars));
    operators[++top_opt] = Boundary;
    int flag_read = 1;   // 循环是否需要新读入 
    int flag_first = 1;  // 第一次不用读 || 数组分析不用读
    enum operator opt = Boundary;
    
    // 循环处理
    while (1) {
        // 读入字符
        if (flag_first) {
            flag_first = 0;
            enum operator pre = opt;
            opt = judgeOpt(hold, pre);

            // 函数边界特殊判断
            if (mode == 2 && opt == RPar) {
                int flag = 1;
                for (int i=0; i<=top_opt; i++) {
                    if (operators[i] == LPar)
                        flag = 0;
                }
                if (flag) opt = Boundary;
            }

            // 出错情况特别判断
            if ((pre == Number || pre == Idt) && (opt == Idt || opt == Number)) {
                printf("wrong priority");
                exit(2);
            }

        }
        else if (flag_read) {
            // 备份上一个hold及opt
            char temp[MAXLEN];
            memset(temp, '\0', sizeof(temp));
            strcpy(temp, hold);
            enum operator pre = opt;
            // 读入新的
            memset(hold, '\0', sizeof(hold));
            fscanf(fp_in, "%s", hold);
            opt = judgeOpt(hold, pre);

            // 函数边界特殊判断
            if (mode == 2 && opt == RPar) {
                int flag = 1;
                for (int i=0; i<=top_opt; i++) {
                    if (operators[i] == LPar)
                        flag = 0;
                }
                if (flag) opt = Boundary;
            }

            // 出错情况特别判断
            if ((pre == Number || pre == Idt) && (opt == Idt || opt == Number)) {
                printf("wrong priority");
                exit(2);
            }

            // 函数情况特别判断
            if (pre == Idt && opt == LPar) {
                Inter_var *result = analyseFuction(fp_in, fp_out, temp);
                if (result == NULL) {
                    printf("Function returns void but to calculated in an exp!\n");
                    exit(3);    // 语义错误
                }
                else {
                    vars[++top_var].value = result->value;
                    vars[top_var].reg = result->reg;
                    vars[top_var].reg_i1 = -1;
                    flag_read = 1;
                    opt = Number;
                    continue;
                }
            } 
            
            // 数组情况特别判断
            if (isArray(temp)) {
                // 获得变量
                slice(temp, 6, strlen(temp)-2);
                Ident *ident = findGlobalItem(temp, table_global);
                if (ident == NULL) {
                    printf("Array cannot found!\n");
                    exit(3);
                }

                // 语义判断
                if (mode == 1 && ident->def != 1) {
                    printf("Const array defination error!\n");
                    exit(3);    // 语义错误
                }

                // 数组相关变量
                int array_reg = 0;

                // 数组检查
                if (ident->dimension > 0) {
                    // 依据下标获得地址
                    Inter_var *indexes[MAXLEN>>6];
                    int index_len = 0;
                    // 具体到元素
                    if (mode != 2) {
                        for (int i=0; i<ident->dimension; i++) {
                            // '['
                            if (strcmp(hold, "LBracket") != 0) {
                                printf("Wrong dimension!\n");
                                exit(3);    // 语义错误
                            }
                            memset(hold, '\0', sizeof(hold));
                            fscanf(fp_in, "%s", hold);

                            // Exp
                            Inter_var *index = analyseExp(fp_in, fp_out, 0);
                            indexes[i] = index;
                            
                            // ']'
                            if (strcmp(hold, "RBracket") != 0) {
                                printf("']' missed!/n");
                                exit(1);    // 语法错误
                            }

                            memset(hold, '\0', sizeof(hold));
                            fscanf(fp_in, "%s", hold);
                        }
                        index_len = ident->dimension;
                    }
                    // 具体到一维
                    else {
                        while (strcmp(hold, "LBracket") == 0) {
                            memset(hold, '\0', sizeof(hold));
                            fscanf(fp_in, "%s", hold);
                            // Exp
                            Inter_var *index = analyseExp(fp_in, fp_out, 0);
                            indexes[index_len++] = index;
                            // ']'
                            if (strcmp(hold, "RBracket") != 0) {
                                printf("']' missed!/n");
                                exit(1);    // 语法错误
                            }
                            memset(hold, '\0', sizeof(hold));
                            fscanf(fp_in, "%s", hold);
                        }
                    }

                    // LLVM
                    // 作为参数传递某一维地址
                    if (index_len < ident->dimension) {
                        // getelementptr
                        // fprintf(fp_out, "\t%%x%d = getelementptr ", ++register_cnt);
                        // printArrayScaleLLVM(fp_out, ident, 0);
                        // fprintf(fp_out, ", ");
                        // printArrayScaleLLVM(fp_out, ident, 0);
                        // if (ident->def == 3 || ident->def == 4) { fprintf(fp_out, "* @%s", ident->name);
                        // } else { fprintf(fp_out, "* %%x%d", ident->address); }
                        // for (int i=0; i<ident->dimension; i++) { fprintf(fp_out, ", i32 0", ident->address); }
                        // fprintf(fp_out, "\n");
                        // array_reg = register_cnt;
                        
                        // 全局数组情况
                        if (ident->def == 3) {
                            fprintf(fp_out, "\t%%x%d = getelementptr ", ++register_cnt);
                            printArrayScaleLLVM(fp_out, ident, 0);
                            fprintf(fp_out, ", ");
                            printArrayScaleLLVM(fp_out, ident, 0);
                            fprintf(fp_out, "* @%s, i32 0, i32 0\n", ident->name);
                            array_reg = register_cnt;
                        }
                        // 非参数情况
                        else if (ident->def != 5) {
                            array_reg = ident->address + 1;
                        } 
                        // 参数情况
                        else {
                            // load
                            if (ident->dimension == 1) {
                                fprintf(fp_out, "\t%%x%d = load i32* , i32* * %%x%d\n", ++register_cnt, ident->address);
                            } else {
                                fprintf(fp_out, "\t%%x%d = load ", ++register_cnt);
                                printArrayScaleLLVM(fp_out, ident, 1);
                                fprintf(fp_out, "*, ");
                                printArrayScaleLLVM(fp_out, ident, 1);
                                fprintf(fp_out, "* * %%x%d\n", ident->address);
                            }
                            array_reg = register_cnt;
                        }
                        
                        // 逐维度确定偏移
                        if (index_len > 0) {
                            fprintf(fp_out, "\t%%x%d = add i32 0, 0\n", ++register_cnt);
                            int reg_total = register_cnt;
                            for (int i=0; i<index_len; i++) {
                                // 维偏移
                                if (indexes[i]->reg == -1) {
                                    fprintf(fp_out, "\t%%x%d = mul i32 %d, %d\n", ++register_cnt, indexes[i]->value, getBlankLoc(ident, i+1)); 
                                } else {
                                    fprintf(fp_out, "\t%%x%d = mul i32 %%x%d, %d\n", ++register_cnt, indexes[i]->reg, getBlankLoc(ident, i+1)); 
                                }
                                // 偏移量相加
                                fprintf(fp_out, "\t%%x%d = add i32 %%x%d, %%x%d\n", register_cnt+1, reg_total, register_cnt);
                                register_cnt++;
                                reg_total = register_cnt;
                            }
                            // 获取到指定维的指针
                            for (int i=1; i<index_len; i++) {
                                fprintf(fp_out, "\t%%x%d = getelementptr ", ++register_cnt);
                                printArrayScaleLLVM(fp_out, ident, i);
                                fprintf(fp_out, ", ");
                                printArrayScaleLLVM(fp_out, ident, i);
                                fprintf(fp_out, "* %%x%d, i32 0, i32 0\n", array_reg, reg_total);
                                array_reg = register_cnt;
                            }
                            // 此时计算出的偏移是以末维长度为单位的，需调整到需要的维度
                            fprintf(fp_out, "\t%%x%d = sdiv i32 %%x%d, %d\n", ++register_cnt, reg_total, getBlankLoc(ident, index_len+1));
                            reg_total = register_cnt;
                            // 依据偏移getelementptr
                            fprintf(fp_out, "\t%%x%d = getelementptr ", ++register_cnt);
                            printArrayScaleLLVM(fp_out, ident, index_len);
                            fprintf(fp_out, ", ");
                            printArrayScaleLLVM(fp_out, ident, index_len);
                            fprintf(fp_out, "* %%x%d, i32 0, i32 %%x%d\n", array_reg, reg_total);
                            array_reg = register_cnt;
                        }
                    }
                    // 形参寻址
                    else if (ident->def == 5) {
                        // load
                        if (ident->dimension == 1) {
                            fprintf(fp_out, "\t%%x%d = load i32* , i32* * %%x%d\n", ++register_cnt, ident->address);
                        } else {
                            fprintf(fp_out, "\t%%x%d = load ", ++register_cnt);
                            printArrayScaleLLVM(fp_out, ident, 1);
                            fprintf(fp_out, "*, ");
                            printArrayScaleLLVM(fp_out, ident, 1);
                            fprintf(fp_out, "* * %%x%d\n", ident->address);
                        }
                        array_reg = register_cnt;
                        // getelementptr
                        if (ident->dimension == 1) {
                            if (indexes[0]->reg == -1) {
                                fprintf(fp_out, "\t%%x%d = getelementptr i32, i32* %%x%d, i32 %d\n", ++register_cnt, array_reg, indexes[0]->value);
                            } else {
                                fprintf(fp_out, "\t%%x%d = getelementptr i32, i32* %%x%d, i32 %%x%d\n", ++register_cnt, array_reg, indexes[0]->reg);
                            }
                            fprintf(fp_out, "\t%%x%d = load i32, i32* %%x%d\n", register_cnt+1, register_cnt);
                            array_reg = ++register_cnt;
                        } else {
                            for (int i=1; i<ident->dimension; i++) {
                                fprintf(fp_out, "\t%%x%d = getelementptr ", ++register_cnt);
                                printArrayScaleLLVM(fp_out, ident, i);
                                fprintf(fp_out, ", ");
                                printArrayScaleLLVM(fp_out, ident, i);
                                fprintf(fp_out, "* %%x%d, i32 0\n", array_reg);
                                array_reg = register_cnt;
                            }                            
                            // 逐维数计算索引
                            fprintf(fp_out, "\t%%x%d = add i32 0, 0\n", ++register_cnt);
                            int reg_total = register_cnt;
                            for (int i=1; i<ident->dimension; i++) {
                                // 维偏移
                                if (indexes[i-1]->reg == -1) {
                                    fprintf(fp_out, "\t%%x%d = mul i32 %d, %d\n", ++register_cnt, indexes[i-1]->value, getBlankLoc(ident, i)); 
                                } else {
                                    fprintf(fp_out, "\t%%x%d = mul i32 %%x%d, %d\n", ++register_cnt, indexes[i-1]->reg, getBlankLoc(ident, i)); 
                                }
                                // 偏移量相加
                                fprintf(fp_out, "\t%%x%d = add i32 %%x%d, %%x%d\n", register_cnt+1, reg_total, register_cnt);
                                register_cnt++;
                                reg_total = register_cnt;
                            }
                            // 计算最后偏移
                            if (indexes[ident->dimension-1]->reg == -1) {
                                fprintf(fp_out, "\t%%x%d = add i32 %%x%d, %d\n", ++register_cnt, reg_total, indexes[ident->dimension-1]->value);
                            } else {
                                fprintf(fp_out, "\t%%x%d = add i32 %%x%d, %%x%d\n", ++register_cnt, reg_total, indexes[ident->dimension-1]->reg);
                            }
                            reg_total = register_cnt;

                            // 根据索引赋值
                            fprintf(fp_out, "\t%%x%d = getelementptr ", ++register_cnt);
                            printArrayScaleLLVM(fp_out, ident, 1);
                            fprintf(fp_out, ", ");
                            printArrayScaleLLVM(fp_out, ident, 1);
                            // 多维修改此处 i32 0 若干
                            fprintf(fp_out, "* %%x%d, i32 0, i32 %%x%d\n", array_reg, reg_total);
                            fprintf(fp_out, "\t%%x%d = load i32, i32* %%x%d\n", register_cnt+1, register_cnt);
                            array_reg = ++register_cnt;
                        }
                    }
                    // 变量寻址
                    else {
                        fprintf(fp_out, "\t%%x%d = getelementptr ", ++register_cnt);
                        printArrayScaleLLVM(fp_out, ident, 0);
                        fprintf(fp_out, ", ");
                        printArrayScaleLLVM(fp_out, ident, 0);
                        if (ident->def == 3 || ident->def == 4) {
                            fprintf(fp_out, "* @%s, i32 0", ident->name);
                        } else {
                            fprintf(fp_out, "* %%x%d, i32 0", ident->address);
                        }
                        for (int i=0; i<ident->dimension; i++) {
                            if (indexes[i]->reg == -1) {
                                fprintf(fp_out, ", i32 %d", indexes[i]->value);
                            } else {
                                fprintf(fp_out, ", i32 %%x%d", indexes[i]->reg);
                            }
                        }
                        fprintf(fp_out, "\n");
                        array_reg = register_cnt;
                        fprintf(fp_out, "\t%%x%d = load i32, i32* %%x%d\n", ++register_cnt, array_reg);
                        array_reg = register_cnt;
                    }

                    // 数组结果处理
                    vars[++top_var].value = 1;
                    vars[top_var].reg = array_reg;
                    vars[top_var].reg_i1 = -1;
                    flag_read = 1;
                    flag_first = 1;
                    opt = Number;
                    continue;
                }
            }

            // Ident延迟入栈
            if (pre == Idt) {
                // 运算数栈存入变量/常量的信息
                slice(temp, 6, strlen(temp)-2);
                Ident *i = findGlobalItem(temp, table_global);
                if (i == NULL) {
                    printTable(table_global);
                    printf("Must be declared!\n");
                    exit(3);    // 语义错误
                }
                else {
                    if (mode == 1 && i->def != 1) {
                        printf("Const defination error!\n");
                        exit(3);    // 语义错误
                    }
                    // 常量
                    if (i->def == 1) {
                        vars[++top_var].value = i->value;
                        vars[top_var].reg = -1;
                        vars[top_var].reg_i1 = -1;
                    }
                    // 全局变量
                    if (i->def == 3 && (mode == 0 || mode == 2)) {
                        vars[++top_var].value = i->value;
                        vars[top_var].reg = ++register_cnt;
                        vars[top_var].reg_i1 = -1;
                        fprintf(fp_out, "\t%%x%d = load i32, i32* @%s\n", register_cnt, i->name);
                    }
                    // 局部变量与参数
                    if ((i->def == 0 || i->def == 5) && (mode == 0 || mode == 2)) {
                        vars[++top_var].value = i->value;
                        vars[top_var].reg = ++register_cnt;
                        vars[top_var].reg_i1 = -1;
                        fprintf(fp_out, "\t%%x%d = load i32, i32* %%x%d\n", register_cnt, i->address);
                    }
                }
            }
        }

        // 分析结束
        if (opt == Boundary && operators[top_opt] == Boundary && top_var != -1) {
            printf("over: %d in %%x%d\n", vars[top_var].value, vars[top_var].reg);
            Inter_var *result;
            result = (Inter_var*)malloc(sizeof(Inter_var));
            result->reg = vars[top_var].reg;
            result->reg_i1 = -1;
            result->value = vars[top_var].value;
            return result;
        }

        // 优先级等于
        else if (priority[operators[top_opt]][opt] == 0) {
            if (top_var == -1 || operators[top_opt] != LPar) {
                printf("parenthesis error");
                exit(2);    // 语法错误
            }
            top_opt--;
            flag_read = 1;
        }
        
        // 优先级小于
        else if (priority[operators[top_opt]][opt] == 1) {
            // 数字常量
            if (opt == Number) {
                if (strncmp(hold, "Dec", 3) == 0) { 
                    slice(hold, 10, strlen(hold)-2); 
                    vars[++top_var].value = D2D(hold);
                    vars[top_var].reg = -1;
                    vars[top_var].reg_i1 = -1;
                }
                if (strncmp(hold, "Oct", 3) == 0) { 
                    slice(hold, 10, strlen(hold)-2);
                    vars[++top_var].value = O2D(hold);
                    vars[top_var].reg = -1; 
                    vars[top_var].reg_i1 = -1;
                }
                if (strncmp(hold, "Hex", 3) == 0) {
                    slice(hold, 10, strlen(hold)-2);
                    vars[++top_var].value = H2D(hold);
                    vars[top_var].reg = -1; 
                    vars[top_var].reg_i1 = -1;
                }           
            }
            // 定义的变量或常量
            else if (opt == Idt) {
                flag_read = 1;
                continue;
            } 
            // 运算符
            else {
                operators[++top_opt] = opt;
            }
            flag_read = 1;
        }

        // 优先级大于
        else if (priority[operators[top_opt]][opt] == 2) {
            specify(fp_out, mode, vars, &top_var, operators[top_opt--]);
            flag_read = 0;
        }

        // 出错
        else if (priority[operators[top_opt]][opt] == 3) {
            printf("Wrong priority\n");
            exit(2);    // 语法错误
        }
    }

    // 释放资源
    free(operators);
    free(vars);
}

enum operator judgeOpt(char str[], enum operator pre) {
    if (strcmp(str, "Plus") == 0) {
        if (pre == Number || pre == Idt || pre == RPar) {
            return Plus;
        } else {
            return UnPlus;
        }
    }
    if (strcmp(str, "Minus") == 0) {
        if (pre == Number || pre == Idt || pre == RPar) {
            return Minus;
        } else {
            return UnMinus;
        }
    }
    if (strcmp(str, "Mult") == 0) { return Mult; }
    if (strcmp(str, "Div") == 0) { return Div; }
    if (strcmp(str, "Rem") == 0) { return Rem; }
    if (strcmp(str, "LPar") == 0) { return LPar; }
    if (strcmp(str, "RPar") == 0) { return RPar; }
    if (strcmp(str, "Rev") == 0) { return Rev; }
    if (strcmp(str, "LBracket") == 0) { return LBracket; }
    if (isNumber(hold)) { return Number; }
    if (isIdentBegin(hold)) { return Idt; }
    return Boundary;
}

void specify(FILE *fp_out, int mode, Inter_var vars[], int *top_var, enum operator opt) {
    // 双目运算
    if (opt != UnPlus && opt != UnMinus && opt != Rev) {
        // 运算数不够
        if (*top_var < 1) {
            printf("Vars not enough(bi)\n");
            exit(2);    // 语法错误 
        }
        // 运算
        Inter_var b = vars[(*top_var)--];
        Inter_var a = vars[(*top_var)--];
        if (opt == Plus) { 
            vars[++(*top_var)].value = a.value + b.value;
            if (mode != 1) { printLLVM(fp_out, vars, top_var, "add", a, b); }
            else { vars[*top_var].reg = -1; }
        }
        if (opt == Minus) { 
            vars[++(*top_var)].value = a.value - b.value;
            if (mode != 1) { printLLVM(fp_out, vars, top_var, "sub", a, b); }
            else { vars[*top_var].reg = -1; }
        }
        if (opt == Mult) { 
            vars[++(*top_var)].value = a.value * b.value;
            if (mode != 1) { printLLVM(fp_out, vars, top_var, "mul", a, b); }
            else { vars[*top_var].reg = -1; }
        }
        if (opt == Div) { 
            vars[++(*top_var)].value = a.value / b.value;
            if (mode != 1) { printLLVM(fp_out, vars, top_var, "sdiv", a, b); }
            else { vars[*top_var].reg = -1; }
        }
        if (opt == Rem) { 
            vars[++(*top_var)].value = a.value % b.value;
            if (mode != 1) { printLLVM(fp_out, vars, top_var, "srem", a, b); }
            else { vars[*top_var].reg = -1; }
        }
    }

    // 单目运算
    else {
        // 运算数不够
        if (*top_var == -1) { 
            printf("Vars not enough(un)\n"); 
            exit(2);    // 语法错误 
        }
        // 运算
        if (opt == UnMinus) {
            if (mode != 1) {
                Inter_var temp;
                temp.value = 0;
                temp.reg = -1;
                temp.reg_i1 = -1;
                printLLVM(fp_out, vars, top_var, "sub", temp, vars[*top_var]);
            }
            vars[*top_var].value *= -1;
        }
        else if (opt == Rev) {
            // LLVM
            if (vars[*top_var].reg == -1) {
                fprintf(fp_out, "\t%%x%d = icmp eq i32 %d, 0\n", ++register_cnt, vars[*top_var].value);
                vars[*top_var].reg_i1 = register_cnt;
            } else {
                if (vars[*top_var].reg_i1 == -1) {
                    fprintf(fp_out, "\t%%x%d = icmp eq i32 %%x%d, 0\n", ++register_cnt, vars[*top_var].reg);
                    vars[*top_var].reg_i1 = register_cnt;
                } else {
                    fprintf(fp_out, "\t%%x%d = icmp eq i1 %%x%d, 0\n", ++register_cnt, vars[*top_var].reg_i1);
                    vars[*top_var].reg_i1 = register_cnt;
                }
            }
            fprintf(fp_out, "\t%%x%d = zext i1 %%x%d to i32\n", ++register_cnt, vars[*top_var].reg_i1);
            vars[*top_var].reg = register_cnt;
            
            // value
            if (vars[*top_var].value != 0) {
                vars[*top_var].value = 0;
            } else {
                vars[*top_var].value = 1;
            }
        }
    }
}

void printLLVM(FILE *fp_out, Inter_var vars[], int *top_var, char *str, Inter_var a, Inter_var b) {
    vars[*top_var].reg = ++register_cnt;
    // i & i
    if (a.reg == -1 && b.reg == -1) {
        fprintf(fp_out, "\t%%x%d = %s i32 %d, %d\n", vars[*top_var].reg, str, a.value, b.value);
    }
    // %i & i
    if (a.reg != -1 && b.reg == -1) {
        fprintf(fp_out, "\t%%x%d = %s i32 %%x%d, %d\n", vars[*top_var].reg, str, a.reg, b.value);
    }
    // i & %i
    if (a.reg == -1 && b.reg != -1) {
        fprintf(fp_out, "\t%%x%d = %s i32 %d, %%x%d\n", vars[*top_var].reg, str, a.value, b.reg); 
    }
    // %i & %i
    if (a.reg != -1 && b.reg != -1) {
        fprintf(fp_out, "\t%%x%d = %s i32 %%x%d, %%x%d\n", vars[*top_var].reg, str, a.reg, b.reg);   
    }
}

void printCondLLVM(FILE *fp_out, char *str, Inter_var *a, Inter_var *b) {
    if (strcmp(str, "or")==0 || strcmp(str, "and")==0) {
        fprintf(fp_out, "\t%%x%d = %s i1 %%x%d, %%x%d\n", ++register_cnt, str, a->reg_i1, b->reg_i1);
        a->reg_i1 = register_cnt;
        if (strcmp(str, "or")==0 && b->value == 1) {
            a->value = 1;
        }
        if (strcmp(str, "and")==0 && b->value == 0) {
            a->value = 0;
        }
    }
    else if (strcmp(str, "eq")==0 || strcmp(str, "ne")==0) {
        if (a->reg == -1 && b->reg == -1) {
            fprintf(fp_out, "\t%%x%d = icmp %s i32 %d, %d\n", ++register_cnt, str, a->value, b->value);
        }
        else if (a->reg != -1 && b->reg == -1) {
            fprintf(fp_out, "\t%%x%d = icmp %s i32 %%x%d, %d\n", ++register_cnt, str, a->reg, b->value);
        }
        else if (a->reg == -1 && b->reg != -1) {
            fprintf(fp_out, "\t%%x%d = icmp %s i32 %d, %%x%d\n", ++register_cnt, str, a->value, b->reg);
        }
        else {
            fprintf(fp_out, "\t%%x%d = icmp %s i32 %%x%d, %%x%d\n", ++register_cnt, str, a->reg, b->reg);
        }
        
        a->reg_i1 = register_cnt;
        
        
        if (strcmp(str, "eq")==0 && b->value == a->value) {
            a->value = 1;
        } else {
            a->value = 0;
        }
        if (strcmp(str, "ne")==0 && b->value != a->value) {
            a->value = 1;
        } else {
            a->value = 0;
        }
    }
    else if (strcmp(str, "sgt") == 0 || strcmp(str, "sge") == 0 || strcmp(str, "slt") == 0 || strcmp(str, "sle") == 0) {
        if (a->reg == -1 && b->reg == -1) {
            fprintf(fp_out, "\t%%x%d = icmp %s i32 %d, %d\n", ++register_cnt, str, a->value, b->value);
        }
        else if (a->reg != -1 && b->reg == -1) {
            fprintf(fp_out, "\t%%x%d = icmp %s i32 %%x%d, %d\n", ++register_cnt, str, a->reg, b->value);
        }
        else if (a->reg == -1 && b->reg != -1) {
            fprintf(fp_out, "\t%%x%d = icmp %s i32 %d, %%x%d\n", ++register_cnt, str, a->value, b->reg);
        }
        else {
            fprintf(fp_out, "\t%%x%d = icmp %s i32 %%x%d, %%x%d\n", ++register_cnt, str, a->reg, b->reg);
        }

        a->reg_i1 = register_cnt;
        fprintf(fp_out, "\t%%x%d = zext i1 %%x%d to i32\n", ++register_cnt, a->reg_i1);
        a->reg = register_cnt;

        // 维护value
        if (strcmp(str, "sgt")==0 && a->value > b->value) {
            a->value = 1;
        } else {
            a->value = 0;
        }
        if (strcmp(str, "sge")==0 && a->value >= b->value) {
            a->value = 1;
        } else {
            a->value = 0;
        }
        if (strcmp(str, "slt")==0 && a->value < b->value) {
            a->value = 1;
        } else {
            a->value = 0;
        }
        if (strcmp(str, "sle")==0 && a->value <= b->value) {
            a->value = 1;
        } else {
            a->value = 0;
        }
    }
}

void printArrayScaleLLVM(FILE *fp_out, Ident *ident, int dim) {
    if (dim == ident->dimension) {
        return;
    }
    else if (dim+1 == ident->dimension) {
        fprintf(fp_out, "[%d x i32] ", ident->index[dim]);
    }
    else {
        fprintf(fp_out, "[%d x ", ident->index[dim]);
        printArrayScaleLLVM(fp_out, ident, dim+1);
        fprintf(fp_out, "] ");
    }
}

int getArrayByte(Ident *ident) {
    int result = 4;
    for (int i=0; i<ident->dimension; i++) {
        result *= ident->index[i];
    }
    return result;
}

int getBlankLoc(Ident *ident, int depth) {
    int result = 1;
    for (int i=depth; i<ident->dimension; i++) {
        result *= ident->index[i];
    }
    return result;
}